package com.huahai.security.core;

import com.huahai.security.core.authentication.filter.CustomAccessDeniedHandler;
import com.huahai.security.core.authentication.filter.CustomAuthenticationEntryPoint;
import com.huahai.security.core.authentication.filter.JwtAuthenticationFilter;
import com.huahai.security.core.authentication.filter.JwtAuthorizationFilter;
import com.huahai.security.core.properties.SecurityProperties;
import com.huahai.security.core.validate.code.ValidateCodeSecurityConfig;
import com.huahai.security.core.authentication.handler.CustomAuthenticationFailureHandler;
import com.huahai.security.core.authentication.handler.CustomAuthenticationSuccessHandler;
import com.huahai.security.core.validate.code.mobile.SmsCodeAuthenticationSecurityConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.cors.CorsUtils;

/**
 * @Author: Jun
 * @Date: 2020/7/17
 *
 * 核心配置类
 */
@Configuration
@EnableConfigurationProperties(SecurityProperties.class)
public class SecurityCoreConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Bean
    public CustomAuthenticationEntryPoint customAuthenticationEntryPoint(){
        return new CustomAuthenticationEntryPoint();
    }

    @Bean
    public CustomAccessDeniedHandler customAccessDeniedHandler(){
        return new CustomAccessDeniedHandler();
    }

    @Autowired
    private SecurityProperties securityProperties;

    @Autowired
    private ValidateCodeSecurityConfig validateCodeSecurityConfig;

    @Autowired
    private SmsCodeAuthenticationSecurityConfig smsCodeAuthenticationSecurityConfig;

    @Autowired
    private CustomAuthenticationFailureHandler customAuthenticationFailureHandler;

    @Autowired
    private CustomAuthenticationSuccessHandler customAuthenticationSuccessHandler;

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.apply(validateCodeSecurityConfig)
                .and()
            .apply(smsCodeAuthenticationSecurityConfig)
                .and()
            .addFilter(new JwtAuthenticationFilter(authenticationManager(),securityProperties,customAuthenticationSuccessHandler))
            .addFilter(new JwtAuthorizationFilter(authenticationManager(),securityProperties,customAuthenticationFailureHandler))
            .authorizeRequests()
                //处理跨域请求中的Preflight请求
                .requestMatchers(CorsUtils::isPreFlightRequest)
                    .permitAll()
                // 构造验证码接口，允许所有人访问
                .antMatchers("/code/image","/code/sms")
                    .permitAll()
                .antMatchers("/album/**").hasRole("admin")
                .anyRequest()
                .authenticated()
            .and()
                // 基于token，所以不需要session
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
                // cors 解决跨域问题
                .cors()
            .and()
                // 关闭跨站请求伪造
                .csrf().disable();
        http.exceptionHandling().accessDeniedHandler(customAccessDeniedHandler());
        http.exceptionHandling().authenticationEntryPoint(customAuthenticationEntryPoint());
    }
}
